using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;

namespace Terra.Core.Common.Utils;

/// <summary>
/// JSON 工具类 (基于 Newtonsoft.Json 实现)
/// </summary>
public static class JsonUtils
{
    #region JsonSerializerSettings

    /// <summary>
    /// 默认 JSON 序列化设置
    /// </summary>
    private static readonly JsonSerializerSettings DefaultSettings = new()
    {
        // 日期格式化
        DateFormatString = "yyyy-MM-dd HH:mm:ss",
        DateTimeZoneHandling = DateTimeZoneHandling.Local,

        // 命名策略
        ContractResolver = new CamelCasePropertyNamesContractResolver(),

        // 空值处理
        NullValueHandling = NullValueHandling.Ignore,

        // 类型名处理
        TypeNameHandling = TypeNameHandling.None,

        // 循环引用处理
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

        // 格式化转换器
        Converters = new List<JsonConverter>
        {
            new StringEnumConverter(),
            new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }
        }
    };

    /// <summary>
    /// 美化输出的 JSON 序列化设置
    /// </summary>
    private static readonly JsonSerializerSettings PrettySettings = new(DefaultSettings)
    {
        Formatting = Formatting.Indented
    };

    #endregion

    #region Serialize Methods

    /// <summary>
    /// 将对象序列化为 JSON 字符串
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="value">要序列化的对象</param>
    /// <param name="pretty">是否美化输出</param>
    /// <returns>JSON 字符串</returns>
    public static string ToJson<T>(T value, bool pretty = false)
    {
        if (value == null) return string.Empty;
        return JsonConvert.SerializeObject(value, pretty ? PrettySettings : DefaultSettings);
    }

    /// <summary>
    /// 将对象序列化为 UTF8 编码的字节数组
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="value">要序列化的对象</param>
    /// <returns>UTF8 编码的字节数组</returns>
    public static byte[] ToJsonBytes<T>(T value)
    {
        if (value == null) return Array.Empty<byte>();
        return System.Text.Encoding.UTF8.GetBytes(ToJson(value));
    }

    #endregion

    #region Deserialize Methods

    /// <summary>
    /// 将 JSON 字符串反序列化为对象
    /// </summary>
    /// <typeparam name="T">目标对象类型</typeparam>
    /// <param name="json">JSON 字符串</param>
    /// <returns>反序列化后的对象</returns>
    public static T FromJson<T>(string json)
    {
        if (string.IsNullOrEmpty(json)) return default;
        return JsonConvert.DeserializeObject<T>(json, DefaultSettings);
    }

    /// <summary>
    /// 将 UTF8 编码的字节数组反序列化为对象
    /// </summary>
    /// <typeparam name="T">目标对象类型</typeparam>
    /// <param name="utf8Json">UTF8 编码的字节数组</param>
    /// <returns>反序列化后的对象</returns>
    public static T FromJson<T>(byte[] utf8Json)
    {
        if (utf8Json == null || utf8Json.Length == 0) return default;
        var json = System.Text.Encoding.UTF8.GetString(utf8Json);
        return FromJson<T>(json);
    }

    /// <summary>
    /// 将 JSON 字符串反序列化为指定类型的对象
    /// </summary>
    /// <param name="json">JSON 字符串</param>
    /// <param name="returnType">目标对象类型</param>
    /// <returns>反序列化后的对象</returns>
    public static object FromJson(string json, Type returnType)
    {
        if (string.IsNullOrEmpty(json)) return null;
        return JsonConvert.DeserializeObject(json, returnType, DefaultSettings);
    }

    #endregion

    #region Try Methods

    /// <summary>
    /// 尝试将对象序列化为 JSON 字符串
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="value">要序列化的对象</param>
    /// <param name="json">输出的 JSON 字符串</param>
    /// <returns>是否序列化成功</returns>
    public static bool TryToJson<T>(T value, out string json)
    {
        try
        {
            json = ToJson(value);
            return true;
        }
        catch
        {
            json = string.Empty;
            return false;
        }
    }

    /// <summary>
    /// 尝试将 JSON 字符串反序列化为对象
    /// </summary>
    /// <typeparam name="T">目标对象类型</typeparam>
    /// <param name="json">JSON 字符串</param>
    /// <param name="value">输出的对象</param>
    /// <returns>是否反序列化成功</returns>
    public static bool TryFromJson<T>(string json, out T value)
    {
        try
        {
            value = FromJson<T>(json);
            return true;
        }
        catch
        {
            value = default;
            return false;
        }
    }

    #endregion

    #region Extended Methods

    /// <summary>
    /// 将对象转换为 JObject
    /// </summary>
    /// <param name="value">要转换的对象</param>
    /// <returns>JObject 对象</returns>
    public static JObject ToJObject(object value)
    {
        if (value == null) return new JObject();
        if (value is JObject jObject) return jObject;
        var json = ToJson(value);
        return FromJson<JObject>(json);
    }

    /// <summary>
    /// 将对象转换为 JArray
    /// </summary>
    /// <param name="value">要转换的对象</param>
    /// <returns>JArray 对象</returns>
    public static JArray ToJArray(object value)
    {
        if (value == null) return new JArray();
        if (value is JArray jArray) return jArray;
        var json = ToJson(value);
        return FromJson<JArray>(json);
    }

    /// <summary>
    /// 将 JSON 字符串转换为动态对象
    /// </summary>
    /// <param name="json">JSON 字符串</param>
    /// <returns>动态对象</returns>
    public static dynamic ToDynamic(string json)
    {
        if (string.IsNullOrEmpty(json)) return new JObject();
        return JsonConvert.DeserializeObject<dynamic>(json, DefaultSettings);
    }

    /// <summary>
    /// 将对象转换为指定类型
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="value">要转换的对象</param>
    /// <returns>转换后的对象</returns>
    public static T ConvertTo<T>(object value)
    {
        if (value == null) return default;
        if (value is T result) return result;
        return FromJson<T>(ToJson(value));
    }

    #endregion
}